package fm.controller;

import com.alibaba.fastjson.JSON;
import fm.dto.NeiyiUser;
import fm.dto.SystemUser;
import fm.entity.AccountBalance;
import fm.entityEnum.ActionTypeEnum;
import fm.entityEnum.OrderEnum;
import fm.exception.BizException;
import fm.mongoService.TokenService;
import fm.sys.token.WebUserToken;
import fm.util.CommonUtils;
import fm.util.Constant;
import fm.web.MediaTypes;
import fm.yichenet.mongo.service.EnginemenService;
import fm.yichenet.mongo.service.MerchantService;
import fm.yichenet.mongo.service.SmsService;
import fm.yichenet.service.AccountBalanceService;
import fm.yichenet.service.OrderService;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static fm.entityEnum.ActionTypeEnum.REGISTER_VERIFY;

/**
 * Created by 63267 on 2017/5/14.
 */
@Controller
@RequestMapping("/user")
public class ClientUserController extends BaseController {
    private static final Logger LOGGER = LoggerFactory.getLogger(ClientUserController.class);

    @Autowired
    fm.mongoService.UserService userService;
    @Autowired
    MerchantService merchantService;
    @Autowired
    EnginemenService enginemenService;

    @Autowired
    AccountBalanceService accountBalanceService;
    @Autowired
    OrderService orderService;

    @Autowired
    SmsService smsService;

    /**
     * 获取信息授权用户信息
     *
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/info", produces = MediaTypes.JSON_UTF_8)
    public String userInfo() throws Exception {
        Map<String, Object> data = new HashedMap();
        try {
            SystemUser user = (SystemUser) getCurrentUser();
            user = userService.getById((String) user.getId());
            if (CommonUtils.isEmpty(user)) {
                throw new BizException("用户不存在，无法获取用户信息");
            }
            Map<String, Object> userData = userObjectToDataMap(user);
            AccountBalance accountBalance = accountBalanceService.addOrGetBalance((String) user.getId());
            if (CommonUtils.isEmpty(accountBalance)) {
                userData.put("account", 0);
            } else {
                userData.put("account", accountBalance.getBalance());
            }

            data.put("data", userData);

            //获取认证资料
//            Map param = new HashMap();
//            param.put("id", user.getId());
//            if (user.getUserType() == 3 || user.getUserType() == 4) {
//                Map authInfo = merchantService.getMerchantAuthInfo(param);
//                data.put("authInfo", authInfo);
//            } else if (user.getUserType() == 2) {
//                Map authInfo = enginemenService.getEnginemenAuthInfo(param);
//                data.put("authInfo", authInfo);
//            }


            this.success(data);
        } catch (Exception ex) {
            LOGGER.error("获取用户信息失败:", ex);
            this.failed(data);
        }
        return JSON.toJSONString(data);
    }

    @ResponseBody
    @RequestMapping(value = "login", produces = MediaTypes.JSON_UTF_8)
    public String login() throws Exception {
        Map<String, Object> data = new HashedMap();
        NeiyiUser user = (NeiyiUser) getCurrentUser();
        Map<String, Object> userData = userObjectToDataMap(user);


        AccountBalance accountBalance = accountBalanceService.addOrGetBalance((String) user.getId());

        if (CommonUtils.isEmpty(accountBalance)) {
            userData.put("account", 0);
        } else {
            userData.put("account", accountBalance.getBalance());
        }
        data.put("user", userData);
        this.success(data);
        return JSON.toJSONString(data);
    }

    public Map<String, Object> userObjectToDataMap(SystemUser user) {
        Map<String, Object> userData = new HashedMap();
        String userJSon = JSON.toJSONString(user);
        userData.putAll(JSON.parseObject(userJSon));

        if (user.getUserType() > 1) {
            long checkOrderAmount = orderService.countShopOrder(OrderEnum.WAIT_EDIT_PRICE, (String) user.getId());
            long payedOrderAmount = orderService.countShopOrder(OrderEnum.PAYMENT_SUCCESS, (String) user.getId());
            userData.put("orderAmount", checkOrderAmount + payedOrderAmount);
            userData.put("checkOrderAmount", checkOrderAmount);
            userData.put("payedOrderAmount", payedOrderAmount);
        }
        return userData;
    }


    @ResponseBody
    @RequestMapping(value = "/update", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public Map updateUserInfo(@RequestBody Map<String, Object> userInfo) throws Exception {
        Map<String, Object> res = new HashedMap();
        try {
            NeiyiUser user = (NeiyiUser) getCurrentUser();
            Map query = new HashMap();
            query.put("_id", user.getId());
            int updateCount = userService.updateUserInfo(query, userInfo);
            Session session = SecurityUtils.getSubject().getSession();
            session.setAttribute(Constant.SESSION_LOGIN_USER, user);
            this.success(res);
        } catch (BizException ex) {
            this.failed(res, ex.getMessage());
        }
        return res;
    }


    /**
     * 发送短信
     *
     * @param phone
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "sendAuthSms", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public Map sendAuthSms(@RequestParam(value = "phone", required = true) String phone) throws Exception {
        Map<String, Object> res = new HashedMap();
        try {
            smsService.businessSmsSend(phone, "REGISTER_VERIFY");
            this.success(res);
        } catch (BizException ex) {
            this.failed(res, ex);
        }
        return res;
    }


    /**
     * 发送短信登录
     *
     * @param phone
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/sendLoginSms", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public Map sendLoginVerifyCode(String phone, String action) {
        Map res = new HashMap();
        try {
            if (org.apache.solr.common.StringUtils.isEmpty(phone) || org.apache.solr.common.StringUtils.isEmpty(action)) {
                throw new BizException("参数缺失");
            }

            NeiyiUser merchant = userService.getUserByPhone(phone);
            if (!ActionTypeEnum.valueOf(action).equals(REGISTER_VERIFY)) {
                if (merchant == null) {
                    throw new BizException("该手机未在平台绑定过商户帐号，请先绑定后再登录!");
                }
            }
            smsService.businessSmsSend(phone, action);
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }

        return res;
    }


    /**
     * 手机信息验证入库（找回旧用户信息）
     *
     * @param phone
     * @param code
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "authUserInfo", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public Map authUserInfo(@RequestParam(value = "phone", required = true) String phone,
                            @RequestParam(value = "code", required = true) String code,
                            String state,
                            @RequestParam(value = "recoverOld", required = false, defaultValue = "false") Boolean recoverOld) throws Exception {
        Map<String, Object> res = new HashedMap();

        try {
            if (StringUtils.isEmpty(state)) {
                throw new BizException("未知的客户端，无法完成绑定!");
            }
            NeiyiUser user = (NeiyiUser) getCurrentUser();
            smsService.checkAuthUserSms(phone, code);

            NeiyiUser dbUser = userService.getUserByPhone(phone);
            if (dbUser != null) {
                throw new BizException("该手机号码已经被使用！");
            }
            if (recoverOld) {
                Map query = new HashMap();
                query.put("_id", user.getId());
                user.setPhone(phone);
                user.setRegType(state);
                int updateCount = userService.updateUserInfo(query, user);
                Session session = SecurityUtils.getSubject().getSession();
                session.setAttribute(Constant.SESSION_LOGIN_USER, user);
            }

            this.success(res);
        } catch (BizException ex) {
            this.failed(res, ex);
        }
        return res;
    }


    @Autowired
    TokenService tokenService;

    @ResponseBody
    @RequestMapping(value = "/auth", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public Map token(String phone, String vrcd) {
        Map res = new HashMap();
        NeiyiUser user = null;
        try {
            if (StringUtils.isNotEmpty(phone) && StringUtils.isNotEmpty(vrcd)) {
                //登录验证码校验 成功：不存在用户 则插入   2。根据ID  phone构建token
                if (userService.checkSms(phone, vrcd)) {
                    user = userService.getUserByPhone(phone);
                    if (user == null) {
                        //TODO 用手机号码登录的新用户 自动创建用户并返回登录成功信息
                        //web_xxxxxxxx
                        user.setPhone(phone);
                        user.setUserType(1);
                        //随机字符串，不长于32 位
                        String randomStr = UUID.randomUUID().toString().replaceAll("-", "");
                        String userName = "web_" + randomStr;
                        user.setAppwebName(userName);

                        userService.addUser(user);
                        user = userService.getUserByPhone(phone);
                    }
                    else{
                        String randomStr = UUID.randomUUID().toString().replaceAll("-", "");
                        String userName = "web" + randomStr;
                        user.setAppwebName(userName);
                    }
                }

                String token = tokenService.buildToken(user.getPhone(), user.getAppwebName());
                new WebUserToken(user.getPhone(), user.getAppwebName());
                res.put("data", token);
                this.success(res);

            } else {
                throw new BizException("请正确填写手机号码与短信验证码!");
            }

        } catch (BizException ex) {
            LOGGER.error("发生错误:", ex);
            this.failed(res, ex.getMessage());
        } catch (UnknownAccountException ex) {
            LOGGER.error("发生错误:", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("发生异常", ex);
            this.failed(res, "服务器发生了未知的错误，请联系管理员或者开发者解决!");
        }
        return res;
    }


    @ResponseBody
    @RequestMapping(value = "addUserByPhone", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public Map addUserByPhone(@RequestParam(value = "phone", required = true) String phone) throws Exception {
        Map<String, Object> res = new HashedMap();
        try {
            NeiyiUser user = new NeiyiUser();
            if (phone != null) {
                user.setPhone(phone);
                user.setUserType(1);
                userService.addUser(user);
            }
            res.put("data", user);
            this.success(res);
        } catch (BizException ex) {
            this.failed(res, ex);
        }
        return res;
    }

    @ResponseBody
    @RequestMapping(value = "getUserByPhone", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public Map getUserByPhone(@RequestParam(value = "phone", required = true) String phone) throws Exception {
        Map<String, Object> res = new HashedMap();
        try {
            NeiyiUser phoneUser = userService.getUserByPhone(phone);
            res.put("data", phoneUser);
            this.success(res);
        } catch (BizException ex) {
            this.failed(res, ex);
        }
        return res;
    }


}


